package pl.edu.agh.jemo.evolution.algorithm.impl;

import java.io.IOException;

import pl.edu.agh.jemo.evolution.objfunc.ObjectiveFunction;
import pl.edu.agh.jemo.evolution.objfunc.impl.FitnessSharingObjectiveFunction;
import pl.edu.agh.jemo.evolution.selections.impl.ClusteredNSGA2CrowdingSelection;

public class ClusteredNSGA2Algorithm extends NSGA2Algorithm {
	
	public ClusteredNSGA2Algorithm() {
		nsga2Selection = new ClusteredNSGA2CrowdingSelection();
	}

	@Override
	public void performInit() {
		loadPopulation();
		childrenPopulation = generateChildPopulation();
		nsga2Selection.setExpectedPopulationSize(populationSize);
	}

	@Override
	protected void step() {
		population.addAll(childrenPopulation);
		/*try {
			calculateMetrics(population);
		} catch (IOException e) {
			e.printStackTrace();
		}*/
		((ClusteredNSGA2CrowdingSelection)nsga2Selection).performClusteredTournament(population, objectiveFunctionSet);
		
		//TODO dodac weightedcostamcostam zeby byl lepszy pareto
		//rozmiar klastra=lepszy wynik
		
		//TODO 2 :
		//   do oceny uzywac fitness sharing, sprawdzac przy calculatephenotype czy instance of ... jesli tak to continue,

		
		childrenPopulation = generateChildPopulation();		
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append(super.toString());
		sb.append(((ClusteredNSGA2CrowdingSelection)nsga2Selection).getClusterizer().toString());		
		return sb.toString();		
	}
	
	@Override
	public void run() {
		try {
			logger.info("Algorithm started\n");
			super.init();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		FitnessSharingObjectiveFunction fitnessSharing = new FitnessSharingObjectiveFunction();
		fitnessSharing.setNicheRadius(.75);
		fitnessSharing.setPopulationReference(population);
		for (currentStep = 0; currentStep < steps; currentStep++) {
			logger.info(String.format("--- Step %d started ---", currentStep+1));
			step();
			logger.info(String.format("--- Step %d finished ---\n", currentStep+1));
			//dla klastrowania inna funkcja do rysowania fenotypu dorbego
/*			ObjectiveFunction function = objectiveFunctionSet.get(objectiveFunctionSet.size()-1);
			objectiveFunctionSet.remove(objectiveFunctionSet.size()-1);
			objectiveFunctionSet.add(fitnessSharing);
			population.setObjectiveFunctionSet(objectiveFunctionSet);
			calculatePhenotype();
			objectiveFunctionSet.remove(objectiveFunctionSet.size()-1);
			objectiveFunctionSet.add(function);
*/			
			plotPopulation();
			try {
				plotter.endStep();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		endAlgorithm();
		try {
			logger.info("Charts are being generated. Please have a sit and wait for a while.");
			plotter.releasePlotter();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		logger.info("Algorithm finished. Have a nice day.");
	}
}
